Amazon Connectのユーザ管理ログをAthenaで取得してみた- Amazon Connect アドベントカレンダー 2022
こんにちは、中川です。
Amazon Connect アドベントカレンダー 2022、3 日目の記事です!
Amazon Connect アドベントカレンダー 2022 はクラスメソッドとギークフィードさんの有志が募ってチャレンジしている企画になります。
今年の 4 月に Amazon Connect ユーザーの作成やセキュリティプロファイルを更新したときの操作が、CloudTrail に出力されるようになるアップデートがありました。
アップデート以前は Amazon Connect インスタンスにログインすることでしか操作履歴を確認できず、出力する機能もなかったため、操作履歴を監査ログとして扱いたい場合に悩ましかったです。
本記事では監査ログとして Amazon Connect ユーザの操作履歴が求められるケースを想定して、Athena でログを取得をしてみます。
やってみた
前提
ログの対象とするユーザ操作関連の API は以下とします。
- CreateUser
- DeleteUser
- UpdateUserIdentityInfo
- UpdateUserSecurityProfiles
- UpdateUserRoutingProfile
- UpdateUserPhoneConfig
- UpdateUserHierarchyStructure
- UpdateUserHierarchyGroupName
- UpdateUserHierarchy
また、事前に Athena では下記ドキュメントを参考に CloudTrail のテーブルを作成していることとします。
Creating the table for CloudTrail logs in Athena using partition projection
そのままログを取得してみる
まずはログのフォーマットを CloudTrail 上から確認します。
以下は CreateUser の抜粋です。実行ユーザの情報は userIdentity.principalId
から取得できそうです。
CreateUser でどのユーザが作成されたかについては requestParameters.Username
から取得できそうです。
次に、DeleteUser や UpdateUserSecurityProfiles のログを確認してみます。
変更対象のユーザについては requestParameters.Username
から取得できそうです。
DeleteUser.
UpdateUserSecurityProfiles.
出力したい情報を確認できたので、クエリを投げてみます。
SELECT
eventtime,
userIdentity.principalId AS executionUser,
eventname,
json_extract_scalar(requestParameters, '$.Username') AS createdUser,
json_extract_scalar(requestParameters, '$.UserId') AS operatedUser,
eventid
FROM
"AwsDataCatalog"."connect"."cloudtrail"
WHERE
eventname in (
'CreateUser',
'DeleteUser',
'UpdateUserIdentityInfo',
'UpdateUserSecurityProfiles',
'UpdateUserRoutingProfile',
'UpdateUserPhoneConfig',
'UpdateUserHierarchyStructure',
'UpdateUserHierarchyGroupName',
'UpdateUserHierarchy'
)
AND region = 'ap-northeast-1'
AND date > '2022/11/01'
AND date <= '2022/12/02'
AND useragent = 'connect.amazonaws.com'
クエリ結果.
ログとしてほしい情報は取れておりますが、以下の点が気になります。
- 操作されたユーザ(operatedUser)がわかりにくい
- 作成されたユーザ(createdUser)のようにメールアドレスで取得できない
- 実行したユーザ(executionUser)がわかりにくい
- 文字列が長い
- 文字数制限によりメールアドレス部分が途中で切れており、正確に出力できてない
クエリを追加して、実行ユーザと操作されたユーザがメールアドレスで表示できることをゴールにしたいと思います。
ユーザ情報をS3にアップロードする
operatedUser や executionUser のメールアドレス前の文字列は、Amazon Connect インスタンスで内部的に使用される UserId です。
ListUsers API を実行することで、Connect インスタンスのユーザ名(メールアドレス)と UserIdD を取得できます。
$ aws connect list-users --instance-id 498ac4af-220c-4a9c-8436-b9c85bXXXXXX
{
"UserSummaryList":[
{
"Id": "1c71831d-8980-43e9-a7c8-4f1aeae10609",
"Arn": "arn:aws:connect:ap-northeast-1:1234XXXXXXXX:instance/498ac4af-220c-4a9c-8436-b9c85bXXXXXX/agent/1c71831d-8980-43e9-a7c8-4f1aeae10609",
"Username": "[email protected]"
},
{
"Id": "51f98508-d413-4434-b890-513e15aa196e",
"Arn": "arn:aws:connect:ap-northeast-1:1234XXXXXXXX:instance/498ac4af-220c-4a9c-8436-b9c85bXXXXXX/agent/51f98508-d413-4434-b890-513e15aa196e",
"Username": "[email protected]"
},
{
"Id": "fb9bd02f-5ea3-4dff-b8d8-61475afe7af6",
"Arn": "arn:aws:connect:ap-northeast-1:1234XXXXXXXX:instance/498ac4af-220c-4a9c-8436-b9c85bXXXXXX/agent/fb9bd02f-5ea3-4dff-b8d8-61475afe7af6",
"Username": "[email protected]"
}
]
}
これを Athena で結合できるようにしたいため、ListUsers の結果を S3 にアップロードする処理を StepFunctions で作ります。
作成したステートマシンは以下になります。ListUsers を実行し、UserSummaryList のユーザ配列ごとに json ファイルを分割して S3 に Put しています。分割して保存することによって、Connect ユーザが削除されたあとにステートマシンを繰り返し実行しても、ユーザ情報を S3 に残すことができます。
{
"Comment": "A description of my state machine",
"StartAt": "ListUsers",
"States": {
"ListUsers": {
"Type": "Task",
"Parameters": {
"InstanceId": "498ac4af-220c-4a9c-8436-b9c85bXXXXXX"
},
"Resource": "arn:aws:states:::aws-sdk:connect:listUsers",
"Next": "Map",
"ResultPath": "$"
},
"Map": {
"Type": "Map",
"InputPath": "$.UserSummaryList",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "INLINE"
},
"StartAt": "PutObject",
"States": {
"PutObject": {
"Type": "Task",
"End": true,
"InputPath": "$",
"Parameters": {
"Body.$": "$",
"Bucket": "connect-user-1234XXXXXXXX",
"Key.$": "$.Id"
},
"Resource": "arn:aws:states:::aws-sdk:s3:putObject"
}
}
},
"End": true
}
}
}
Athena でクエリを投げ、ユーザー情報を取得できるか確認します。
テーブルを作成し、SELECT を実行すると以下のようにユーザ情報を取得できました。
CREATE EXTERNAL TABLE IF NOT EXISTS connect_users (
Arn string,
Id string,
Username string
) ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://connect-user-1234XXXXXXXX/'
出力結果.
ユーザ管理ログを取得する
準備ができましたので、テーブルを結合してユーザ管理ログを取得してみます。
WITH
user_data AS (
SELECT *
FROM
"AwsDataCatalog"."connect"."connect_users"
),
log_data AS (
SELECT
eventtime,
substring(userIdentity.principalId, 23, 36) AS executeuserid,
eventname,
json_extract_scalar(requestParameters, '$.Username') AS createdUser,
json_extract_scalar(requestParameters, '$.UserId') AS operatedUser,
eventId
FROM
"AwsDataCatalog"."connect"."cloudtrail"
WHERE
eventname in ('CreateUser',
'DeleteUser',
'UpdateUserIdentityInfo',
'UpdateUserSecurityProfiles',
'UpdateUserRoutingProfile',
'UpdateUserPhoneConfig',
'UpdateUserHierarchyStructure',
'UpdateUserHierarchyGroupName',
'UpdateUserHierarchy')
AND region = 'ap-northeast-1'
AND date > '2022/11/01'
AND date <= '2022/12/02'
AND useragent = 'connect.amazonaws.com'
)
SELECT
log_data.eventtime AS EventTime,
J1.username AS ExecuteUser,
log_data.eventname AS EventName,
log_data.username AS CreatedUser,
J2.username AS OperatedUser,
log_data.eventId AS EventId
FROM
log_data
LEFT JOIN user_data AS J1 ON log_data.executeuserid = J1.id
LEFT JOIN user_data AS J2 ON log_data.objectid = J2.id
出力結果.
実行ユーザ、操作されたユーザをメールアドレスで表示できることを確認できました!
さいごに
Amazon Connect のユーザ管理のログを Athena で出力してみました。
そのまま出力した場合は Connect 内部ユーザ ID で出力されるため、ユーザ情報の付け合せが必要となり使い勝手がよろしくありませんでした。
ユーザ情報の一覧を取得する API を組み合わせることによって、ログとして扱いやすくなります。
今回は StepFunctions を 1 回だけ実行しましたが、実際の環境で使う場合はスケジューリングや Athena の実行と合わせて行うなどご検討ください。